home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_pcdp / ada / tm.ada < prev    next >
Text File  |  1996-01-30  |  6KB  |  213 lines

  1. with Semaphore_Package; use Semaphore_Package;
  2. with Text_IO; use Text_IO; 
  3. procedure TM is
  4.  
  5.   type Node_Count is range 0..4;
  6.   subtype Node_ID is Node_Count range 1..Node_Count'Last;
  7.  
  8.   task type Nodes is
  9.     entry Init(ID: Node_ID; N_I, N_O: Node_Count);
  10.     entry Configure(C: Node_ID);
  11.     entry Message(M: Integer; ID: Node_ID);
  12.     entry Signal(ID: Node_ID);
  13.   end Nodes;
  14.  
  15.   Node: array(Node_ID) of Nodes;
  16.  
  17.   task body Nodes is
  18.  
  19.     type Edge is
  20.       record
  21.         Exists:  Boolean := False;
  22.         Active:  Boolean := False;
  23.         Marker_Received: Boolean := False;
  24.       end record;
  25.  
  26.     Incoming: array(Node_ID) of Edge;
  27.     Outgoing: array(Node_ID) of Edge;
  28.     First_Edge:  Node_Count := 0;
  29.     N_In, N_Out: Node_Count := 0;
  30.     N_Signals:   Natural := 0;
  31.  
  32.     pragma Volatile(N_Signals);
  33.     pragma Volatile(First_Edge);
  34.     pragma Volatile(Incoming);
  35.     pragma Volatile(Outgoing);
  36.  
  37.     I: Node_ID;
  38.     S: Binary_Semaphore := Init(1);
  39.     Received_ID: Node_ID;
  40.     Received_Data: Integer;
  41.  
  42.     task Main_Process is
  43.       entry Init;
  44.     end Main_Process;
  45.  
  46.     task body Main_Process is
  47.       Count: Integer := 0;
  48.       Markers_Sent: Boolean := False;
  49.  
  50.       procedure Send_Messages(Data: Integer) is
  51.       begin
  52.         for J in Node_ID loop
  53.           if Outgoing(J).Exists then
  54.              Put_Line("  " & Node_ID'Image(I) & " sending  " &
  55.                      Integer'Image(Data) & " to   " &
  56.                      Node_ID'Image(J));
  57.              if not Outgoing(J).Active then
  58.                Outgoing(J).Active := True;
  59.                Wait(S);
  60.                N_Signals := N_Signals + 1;
  61.                Signal(S);
  62.              end if;
  63.              Node(J).Message(Data, I);
  64.           end if;
  65.         end loop;
  66.       end Send_Messages;
  67.  
  68.       function Decide_to_Terminate return Boolean is
  69.  
  70.         procedure Send_Signals(ID: Node_ID) is
  71.         begin
  72.           Put_Line("  " & Node_ID'Image(I) & " sending signal to " &
  73.                    Node_ID'Image(ID));
  74.           Node(ID).Signal(I);
  75.           Incoming(ID).Active := False;
  76.         end Send_Signals;
  77.  
  78.       begin
  79.         for J in Node_ID loop
  80.           if  J /= First_Edge and then
  81.               Incoming(J).Active then
  82.                 Send_Signals(J);
  83.           end if;
  84.         end loop;
  85.  
  86.         if N_Signals = 0 then
  87.           if I = 1 then
  88.             Put_Line("  " & Node_ID'Image(I) & " program terminated ");
  89.           elsif First_Edge /= 0 then
  90.             Send_Signals(First_Edge);
  91.             First_Edge := 0;
  92.           end if;
  93.           return True;
  94.         else 
  95.           return False;
  96.         end if;
  97.       end Decide_to_Terminate;
  98.  
  99.       function Received_Markers return Boolean is
  100.       begin
  101.         for J in Node_ID loop
  102.           if Incoming(J).Exists and then
  103.              not Incoming(J).Marker_Received then
  104.                return False;
  105.           end if;
  106.         end loop;
  107.         return True;
  108.       end Received_Markers;
  109.  
  110.     begin
  111.       accept Init;
  112.       if I = 1 then 
  113.         Send_Messages(Count);
  114.         Send_Messages(Count);
  115.         Send_Messages(-1);
  116.         loop
  117.           exit when Decide_to_Terminate;
  118.           delay 0.01;
  119.         end loop;
  120.       else
  121.         loop
  122.           if Count < 5 then
  123.             if First_Edge /= 0 then
  124.                Count := Count + 1;
  125.                Send_Messages(Count);
  126.             end if;
  127.           elsif not Markers_Sent then
  128.             if Incoming(First_Edge).Marker_Received then
  129.               Send_Messages(-1);
  130.               Markers_Sent := True;
  131.             end if;
  132.           elsif Received_Markers then
  133.               loop
  134.                 exit when Decide_to_Terminate;
  135.                 delay 0.01;
  136.               end loop;
  137.               exit;
  138.           end if;
  139.           delay 0.01;
  140.         end loop;
  141.       end if;
  142.     end Main_Process;
  143.  
  144.   begin
  145.     accept Init(ID: Node_ID; N_I, N_O: Node_Count) do
  146.       I := ID;
  147.       N_In  := N_I;
  148.       N_Out := N_O;
  149.     end Init;
  150.     for J in 1..N_In loop
  151.       accept Configure(C: Node_ID) do
  152.         Incoming(C).Exists := True;
  153.       end Configure;
  154.     end loop;
  155.     for J in 1..N_Out loop
  156.       accept Configure(C: Node_ID) do
  157.         Outgoing(C).Exists := True;
  158.       end Configure;
  159.     end loop;
  160.  
  161.     Main_Process.Init;
  162.  
  163.     loop
  164.       select 
  165.         accept Message(M: Integer; ID: Node_ID) do
  166.           Put_Line("  " & Node_ID'Image(I) & " received " &
  167.                    Integer'Image(M) & " from " &
  168.                    Node_ID'Image(ID));
  169.           Received_ID := ID;
  170.           Received_Data := M;
  171.         end Message;
  172.         if Received_Data < 0 then
  173.           Incoming(Received_ID).Marker_Received := True;
  174.         else
  175.           if First_Edge = 0 then
  176.             First_Edge := Received_ID;
  177.           end if;
  178.         end if;
  179.         if not Incoming(Received_ID).Active then 
  180.           Incoming(Received_ID).Active := True;
  181.         end if;
  182.       or
  183.         accept Signal(ID: Node_ID) do
  184.           Put_Line("  " & Node_ID'Image(I) & " received signal from " &
  185.                    Node_ID'Image(ID));
  186.           Received_ID := ID;
  187.         end Signal;
  188.         Outgoing(Received_ID).Active := False;
  189.         Wait(S);
  190.         N_Signals := N_Signals - 1;
  191.         Signal(S);
  192.       or
  193.         terminate;
  194.       end select;
  195.     end loop;
  196.   end Nodes;
  197.  
  198. begin
  199.   Node(1).Init(1,0,2); 
  200.   Node(1).Configure(2); Node(1).Configure(3);
  201.  
  202.   Node(2).Init(2,2,2); 
  203.   Node(2).Configure(1); Node(2).Configure(3);
  204.   Node(2).Configure(3); Node(2).Configure(4);
  205.  
  206.   Node(3).Init(3,3,1); 
  207.   Node(3).Configure(1); Node(3).Configure(2);
  208.   Node(3).Configure(4); Node(3).Configure(2);
  209.  
  210.   Node(4).Init(4,1,1); 
  211.   Node(4).Configure(2); Node(4).Configure(3);
  212. end TM;
  213.